// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// I [author] rhyme_lph
// q [email]  rhymelph@gmail.com
// Y [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:dio/dio.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/cpf_contribution_entity.dart';
import 'package:finance_app/src/entities/suggest_date_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/http_service/http_cpf_contribution_service.dart';
import 'package:finance_app/src/http_service/http_setting_service.dart';
import 'package:finance_app/src/mixin/init_edit_data_mixin.dart';
import 'package:finance_app/src/mixin/year_month_select_mixin.dart';
import 'package:finance_app/src/page/dashboard/amount_gst/amount_gst_rate_category_page.dart';
import 'package:finance_app/src/provider/hr_payroll/hr_and_payroll_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/payroll_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/utils/permission_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:flutter/material.dart';

class RecordCpfContributionProvider extends BaseProvider<CpfContributionEntity>
    with YearMonthSelectMixin, InitEditDataMixin<CpfContributionEntity> {
  TextEditingController employerCpfController = TextEditingController();
  TextEditingController employeeCpfController = TextEditingController();
  TextEditingController cpfLateController = TextEditingController();
  TextEditingController fwlController = TextEditingController();
  TextEditingController fwlLateController = TextEditingController();
  TextEditingController sdlController = TextEditingController();

  TextEditingController communityController = TextEditingController();
  TextEditingController communityDonorController = TextEditingController();

  TextEditingController mbmfController = TextEditingController();
  TextEditingController mbmfDonorController = TextEditingController();

  TextEditingController sindaController = TextEditingController();
  TextEditingController sindaDonorController = TextEditingController();

  TextEditingController cdacController = TextEditingController();
  TextEditingController cdacDonorController = TextEditingController();

  TextEditingController ecfController = TextEditingController();
  TextEditingController ecfDonorController = TextEditingController();

  num cpfTotal = 0;

  num grandTotal = 0;

  DateTime date;

  @override
  Future<Response> get dataFuture async {
    if (data?.id != null) {
      return HttpCpfContributionService.getCpfContributionID(data.id);
    } else {
      await post(HttpSettingService.getSuggestTime(type), onSuccess: (result) {
        SuggestDateEntity suggestDateEntity =
            getEntityFromResult<SuggestDateEntity>(result);
        final dateString = suggestDateEntity.typeDate ??
            suggestDateEntity.financialYearDate.start;
        date = DateTime.tryParse(dateString).toLocal() ?? DateTime.now();
      });
      return HttpCpfContributionService.getCpfContributionByYearMonth(
        year: int.tryParse(DateTimeUtils.formatYear(date)),
        month: DateTimeUtils.formatMonth(date, 'MMM'),
      );
    }
  }

  Future getCPFByYearMonth() async {}

  List<String> menuList = ['Edit', 'Record Payment', 'Delete'];

  @override
  void initState() {
    init(data?.id);
    super.initState();

    // if (data?.startDate != null) {
    //   date = DateTime.parse(data.startDate);
    // }
    employerCpfController.addListener(() {
      calCpfTotalContribution();
      calGrandTotal();
    });
    employeeCpfController.addListener(() {
      calCpfTotalContribution();
      calGrandTotal();
    });
    cpfLateController.addListener(calGrandTotal);
    fwlController.addListener(calGrandTotal);
    fwlLateController.addListener(calGrandTotal);
    sdlController.addListener(calGrandTotal);
    communityController.addListener(calGrandTotal);
    mbmfController.addListener(calGrandTotal);
    sindaController.addListener(calGrandTotal);
    cdacController.addListener(calGrandTotal);
    ecfController.addListener(calGrandTotal);
  }

  @override
  void dispose() {
    employerCpfController.dispose();
    employeeCpfController.dispose();
    cpfLateController.dispose();
    fwlController.dispose();
    fwlLateController.dispose();
    sdlController.dispose();
    communityController.dispose();
    communityDonorController.dispose();
    mbmfController.dispose();
    mbmfDonorController.dispose();
    sindaController.dispose();
    sindaDonorController.dispose();
    cdacController.dispose();
    cdacDonorController.dispose();
    ecfController.dispose();
    ecfDonorController.dispose();
    super.dispose();
  }

  void onSave() {
    FocusManager.instance.primaryFocus.unfocus();
    obtainContext?.call((context) async {
      if (isEdit) {
        await post(
            HttpCpfContributionService.updateCpfContribution(
              data.id,
              start_date: data.startDate,
              end_date: data.endDate,
              year: data.year,
              month: data.month,
              status: data.status,
              company_id: data.companyID,
              total: grandTotal,
              employee_cpf: num.tryParse(employeeCpfController.text) ?? 0,
              employer_cpf: num.tryParse(employerCpfController.text) ?? 0,
              cpf_overdue_interest: num.tryParse(cpfLateController.text) ?? 0,
              fwl: num.tryParse(fwlController.text) ?? 0,
              fwl_overdue_interest: num.tryParse(fwlLateController.text) ?? 0,
              sdl: num.tryParse(sdlController.text) ?? 0,
              community_donation: num.tryParse(communityController.text) ?? 0,
              community_donation_donors:
                  int.tryParse(communityDonorController.text) ?? 0,
              mbmf: num.tryParse(mbmfController.text) ?? 0,
              mbmf_donors: int.tryParse(mbmfDonorController.text) ?? 0,
              sinda: num.tryParse(sindaController.text) ?? 0,
              sinda_donors: int.tryParse(sindaDonorController.text) ?? 0,
              cdac: num.tryParse(cdacController.text) ?? 0,
              cdac_donors: int.tryParse(cdacDonorController.text) ?? 0,
              ecf: num.tryParse(ecfController.text) ?? 0,
              ecf_donors: int.tryParse(ecfDonorController.text) ?? 0,
            ),
            autoHandler: AutoHandler.Toast,
            loadingTip: S.current.loading, onSuccess: (result) async {
          await showGotItTipBottomSheet(
              context, S.current.the_cpf_contribution_has_been_recorded);
          isEdit = false;
          data = transformData(
              getEntityFromResult<CpfContributionEntity>(result), false);
          if (data != null) {
            Providers.get<HrAndPayrollProvider>(
                    RouterGenProviders.hrAndPayrollPage, null)
                ?.getChildProvider<PayrollProvider>()
                ?.updateCpfItem(data);
            if (!Config.hasPermission(PermissionUtils.homeDashboard))
              Config.dashboardProvider
                  ?.getChildProvider<HrAndPayrollProvider>()
                  ?.getChildProvider<PayrollProvider>()
                  ?.updateCpfItem(data);
          }
          update();
        });
      } else {
        await post(
            HttpCpfContributionService.createCpfContribution(
              start_date: data.startDate,
              end_date: data.endDate,
              year: data.year,
              month: data.month,
              status: data.status,
              company_id: data.companyID,
              total: grandTotal,
              employee_cpf: num.tryParse(employeeCpfController.text) ?? 0,
              employer_cpf: num.tryParse(employerCpfController.text) ?? 0,
              cpf_overdue_interest: num.tryParse(cpfLateController.text) ?? 0,
              fwl: num.tryParse(fwlController.text) ?? 0,
              fwl_overdue_interest: num.tryParse(fwlLateController.text) ?? 0,
              sdl: num.tryParse(sdlController.text) ?? 0,
              community_donation: num.tryParse(communityController.text) ?? 0,
              community_donation_donors:
                  int.tryParse(communityDonorController.text) ?? 0,
              mbmf: num.tryParse(mbmfController.text) ?? 0,
              mbmf_donors: int.tryParse(mbmfDonorController.text) ?? 0,
              sinda: num.tryParse(sindaController.text) ?? 0,
              sinda_donors: int.tryParse(sindaDonorController.text) ?? 0,
              cdac: num.tryParse(cdacController.text) ?? 0,
              cdac_donors: int.tryParse(cdacDonorController.text) ?? 0,
              ecf: num.tryParse(ecfController.text) ?? 0,
              ecf_donors: int.tryParse(ecfDonorController.text) ?? 0,
            ),
            autoHandler: AutoHandler.Toast,
            loadingTip: S.current.loading, onSuccess: (result) async {
          await showGotItTipBottomSheet(
              context, S.current.the_cpf_contribution_has_been_recorded);
          isEdit = false;
          data = transformData(
              getEntityFromResult<CpfContributionEntity>(result), false);
          update();
          Providers.get<HrAndPayrollProvider>(
                  RouterGenProviders.hrAndPayrollPage, null)
              ?.getChildProvider<PayrollProvider>()
              ?.refreshController
              ?.requestRefresh();
          if (!Config.hasPermission(PermissionUtils.homeDashboard))
            Config.dashboardProvider
                ?.getChildProvider<HrAndPayrollProvider>()
                ?.getChildProvider<PayrollProvider>()
                ?.refreshController
                ?.requestRefresh();
        });
      }
    });
  }

  @override
  void onRequestRefresh() {
    post(
        HttpCpfContributionService.getCpfContributionByYearMonth(
          year: int.parse(DateTimeUtils.formatYear(date)),
          month: DateTimeUtils.formatMonth(date, 'MMM'),
        ),
        autoHandler: AutoHandler.Toast,
        loadingTip: S.current.loading, onSuccess: (result) {
      data = transformData(
          getEntityFromResult<CpfContributionEntity>(result), false);
      isEdit = false;
      update();
    });
  }

  @override
  Future get editDataFuture =>
      HttpCpfContributionService.getCpfContributionID(data.id);

  @override
  TextEditingController get numberCtl => null;

  void onSelectMenu(String value) {
    switch (value) {
      case 'Edit':
        onChangeEditMode();
        break;
      case 'Record Payment':
        onRecordPayment();
        break;
      case 'See Payment':
        onSeePayment();
        break;
      case 'Delete':
        onDelete();
        break;
    }
  }

  void onRecordPayment() async {
    var result = await Routes.navigateTo(RouterGenProviders.newCashOutPage,
        params: {
          'cpfData': data,
          'currency': SettingDataCurrency()..key = 'SGD'
        });
    if (result == 'closed') {
      loadData();
    }
  }

  void onSeePayment() async {
    await Routes.navigateTo(RouterGenProviders.newCashOutPage, params: {
      'data': TransactionEntity()
        ..transactionableId = data?.payments?.first?.id,
      'isSelectMode': true
    });
    loadData();
  }

  void onDelete() async {
    obtainContext?.call((context) async {
      bool isSuccess = await showDeleteCpfContributionBottomSheet(context);
      if (isSuccess == true) {
        isSuccess = false;
        await post(HttpCpfContributionService.deleteCpfContribution(data.id),
            loadingTip: S.current.loading,
            autoHandler: AutoHandler.Toast, onSuccess: (result) {
          isSuccess = true;
        });
        if (isSuccess == true) {
          await showDeleteSuccessTipBottomSheet(context);
          Navigator.of(context).pop({
            'delete': true,
          });
        }
      }
    });
  }

  @override
  FutureOr<CpfContributionEntity> transformData(
      CpfContributionEntity d, bool isCache) {
    if (d != null) {
      d.employerCpf == 0
          ? employerCpfController.clear()
          : employerCpfController.text = d.employerCpf.toStringAsNotFixed(0);
      d.employeeCpf == 0
          ? employeeCpfController.clear()
          : employeeCpfController.text = d.employeeCpf.toStringAsFixed(0);
      d.cpfOverdueInterest == 0
          ? cpfLateController.clear()
          : cpfLateController.text = d.cpfOverdueInterest.toStringAsFixed(2);
      d.fwl == 0
          ? fwlController.clear()
          : fwlController.text = d.fwl.toStringAsFixed(2);
      d.fwlOverdueInterest == 0
          ? fwlLateController.clear()
          : fwlLateController.text = d.fwlOverdueInterest.toStringAsFixed(2);
      d.sdl == 0
          ? sdlController.clear()
          : sdlController.text = d.sdl.toStringAsFixed(2);
      d.communityDonation == 0
          ? communityController.clear()
          : communityController.text = d.communityDonation.toStringAsFixed(2);
      d.communityDonationDonors == 0
          ? communityDonorController.clear()
          : communityDonorController.text =
              d.communityDonationDonors.toString();
      d.mbmf == 0
          ? mbmfController.clear()
          : mbmfController.text = d.mbmf.toStringAsFixed(2);
      d.mbmfDonors == 0
          ? mbmfController.clear()
          : mbmfDonorController.text = d.mbmfDonors.toString();
      d.sinda == 0
          ? sindaController.clear()
          : sindaController.text = d.sinda.toStringAsFixed(2);
      d.sindaDonors == 0
          ? sindaDonorController.clear()
          : sindaDonorController.text = d.sindaDonors.toString();
      d.cdac == 0
          ? cdacController.clear()
          : cdacController.text = d.cdac.toStringAsFixed(2);
      d.cdacDonors == 0
          ? cdacDonorController.clear()
          : cdacDonorController.text = d.cdacDonors.toString();
      d.ecf == 0
          ? ecfController.clear()
          : ecfController.text = d.ecf.toStringAsFixed(2);
      d.ecfDonors == 0
          ? ecfDonorController.clear()
          : ecfDonorController.text = d.ecfDonors.toString();
      date = DateTime.parse(d.startDate);
      calGrandTotal();
      calCpfTotalContribution();
      if (d.status == 'closed') {
        menuList = ['See Payment'];
      } else {
        menuList = ['Edit', 'Record Payment', 'Delete'];
      }

      Providers.get<HrAndPayrollProvider>(
              RouterGenProviders.hrAndPayrollPage, null)
          ?.getChildProvider<PayrollProvider>()
          ?.updateCpfStatus(id, d.status);

      if (!Config.hasPermission(PermissionUtils.homeDashboard))
        Config.dashboardProvider
            ?.getChildProvider<HrAndPayrollProvider>()
            ?.getChildProvider<PayrollProvider>()
            ?.updateCpfStatus(id, d.status);
    }

    return super.transformData(d, isCache);
  }

  void calCpfTotalContribution() {
    cpfTotal = (num.tryParse(employeeCpfController.text) ?? 0) +
        (num.tryParse(employerCpfController.text) ?? 0);
    update();
  }

  void calGrandTotal() {
    grandTotal = (num.tryParse(employeeCpfController.text) ?? 0) +
        (num.tryParse(employerCpfController.text) ?? 0) +
        (num.tryParse(cpfLateController.text) ?? 0) +
        (num.tryParse(fwlController.text) ?? 0) +
        (num.tryParse(fwlLateController.text) ?? 0) +
        (num.tryParse(sdlController.text) ?? 0) +
        (num.tryParse(communityController.text) ?? 0) +
        (num.tryParse(mbmfController.text) ?? 0) +
        (num.tryParse(sindaController.text) ?? 0) +
        (num.tryParse(cdacController.text) ?? 0) +
        (num.tryParse(ecfController.text) ?? 0);

    update();
  }

  @override
  String get type => 'cpf_contribution';
}
